package cn.buk.tms.flight.service;

import cn.buk.api.szkj.dto.eterm.DetrFlightInfo;
import cn.buk.api.szkj.dto.eterm.request.*;
import cn.buk.api.szkj.dto.eterm.response.*;
import cn.buk.api.szkj.service.SzkjEtermService;
import cn.buk.common.util.DateUtil;
import cn.buk.common.util.FlightTicketUtil;
import cn.buk.qms.service.BaseFlightOrderService;
import cn.buk.tms.dao.DetrDao;
import cn.buk.tms.dao.FlightOrderDao;
import cn.buk.tms.dao.FlightPolicyDao;
import cn.buk.tms.entity.misc.*;
import cn.buk.tms.entity.order.flight.*;
import cn.buk.tms.flight.dao.KeyCustomerPolicyDao;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static cn.buk.common.Constant.*;

/**
 * @author yfdai
 */
@Service
public class EtermServiceImpl extends BaseFlightOrderService implements EtermService {

  private static final Logger logger = LogManager.getLogger(EtermServiceImpl.class);

  @Autowired
  public EtermServiceImpl(FlightOrderDao flightOrderDao,
                          DetrDao detrDao,
                          KeyCustomerPolicyDao keyCustomerPolicyDao,
                          FlightPolicyDao flightPolicyDao
  ) {
    this.flightOrderDao = flightOrderDao;
    this.detrDao = detrDao;
    this.keyCustomerPolicyDao = keyCustomerPolicyDao;
    this.flightPolicyDao = flightPolicyDao;
  }

  private final KeyCustomerPolicyDao keyCustomerPolicyDao;
  private final DetrDao detrDao;

  private final FlightPolicyDao flightPolicyDao;






  @Override
  public void checkPriceOfChangeOrders(int enterpriseId, String agentName) {
    //查找需要生成编码的改签单
    final Date startDate = DateUtil.addDays(DateUtil.getCurDate(), -1);
    List<FlightChangeOrder> changeOrders = changeOrderDao.searchChangeOrdersNeedPriceCheck(enterpriseId, startDate);

    //国内改签生成编码
    for (FlightChangeOrder changeOrder : changeOrders) {
      execCheckPriceOfChangeOrder(enterpriseId, agentName, changeOrder);
    }
  }

  /**
   * 对改签单的价格进行检查
   */
  private void execCheckPriceOfChangeOrder(final int enterpriseId, final String username, FlightChangeOrder changeOrder) {
    if (changeOrder.getIntlTicket() == 1) {
      return;
    }

    if (changeOrder.getNewPnrNo() != null) {
      return;
    }

    //判断所属客户是否停用了
    if (changeOrder.getCustomer() == null) {
      doSendAlert(enterpriseId, "改签单(" + changeOrder.getOrderNo() + ")未找到所属客户。", null, EntDepartment.DEPT_ADMINISTRATOR);
      return;
    }
    if (changeOrder.getCustomer().getStatus() == 0) {
      doSendAlert(enterpriseId, "改签单(" + changeOrder.getOrderNo() + ")所属客户(" + changeOrder.getCustomer().getVipName() + ")处于停用状态。", null, EntDepartment.DEPT_ADMINISTRATOR);
      return;
    }
    if (changeOrder.getCustomer().getTestMode() == 1) {
      doSendAlert(enterpriseId, "改签单(" + changeOrder.getOrderNo() + ")所属客户(" + changeOrder.getCustomer().getVipName() + ")处于测试模式，请人工处理。", null, EntDepartment.DEPT_ADMINISTRATOR);
      return;
    }

    //非客服预订的才生成编码
    final String operator = changeOrder.getOperator();
    User user = userDao.getUserByUsername(operator);
    if (user == null || user.getParentEnterprise() != enterpriseId) {
      return;
    }

    doCheckChangeOrderPrice(changeOrder, username);
  }



  /**
   * 校验改签单的价格
   */
  private void doCheckChangeOrderPrice(FlightChangeOrder changeOrder, String username) {
    final int enterpriseId = changeOrder.getEnterpriseId();
    final int orderId = changeOrder.getId();

    //预订编码
    PnrCreateRequest request = new PnrCreateRequest();
    request.getBaseInfo().setPnrType("ADU");

    CreatePnrPassenger psg = new CreatePnrPassenger();
    psg.setName(changeOrder.getPsgName());
    psg.setIdNo(changeOrder.getIdNo());

    if (changeOrder.getMobile() == null || changeOrder.getMobile().trim().length() < 5) {
      //试试从对应的机票订单中去查找
      String mobile = getPsgMobileFromFlightOrder(changeOrder.getEnterpriseId(), changeOrder.getOrderNo(),
              changeOrder.getPsgName().trim(), changeOrder.getIdNo().trim());
      psg.setPhone(mobile);
    } else {
      psg.setPhone(changeOrder.getMobile().trim());
    }
    request.getPassengers().add(psg);

    for (FlightChangeOrderDetail fltOrder : changeOrder.getFlights()) {
      if (fltOrder.getFlightType() != 1) {
        continue;
      }
      CreatePnrFlight flt = new CreatePnrFlight();
      flt.setDport(fltOrder.getFlight().getDport());
      flt.setAport(fltOrder.getFlight().getAport());
      flt.setDdate(fltOrder.getFlight().getDdate());
      flt.setFlightNo(fltOrder.getFlight().getFlightNo().substring(2));
      flt.setCarrier(fltOrder.getFlight().getFlightNo().substring(0, 2));
      flt.setSubclass(fltOrder.getFlight().getSubclass());
      request.getFlights().add(flt);
    }

    final int queryId = userDao.createEtermCmdLog(enterpriseId, username, "生成编码", changeOrder.getChangeOrderNo());

    SzkjEtermService szkjEtermService = createSzkjEtermService(enterpriseId);

    CreatePnrResponse response = szkjEtermService.createPnr(getEtermUsername(enterpriseId), getEtermPassword(enterpriseId), queryId, request);
    userDao.updateEtermCmdLog(queryId, response.getRequestStr(), response.getResponseStr());

    if (response.getCode() == 1) {
      //接口调用成功
      final String pnrNo = response.getPnrInfo().getPnr();
      changeOrderDao.updateChangeOrderNewPnrNo(enterpriseId, username, orderId, pnrNo);
    } else {
      //生成编码失败
      changeOrderDao.appendFlightChangeOrderLog(enterpriseId, orderId, username, response.getMsg());
      changeOrderDao.updateChangeOrderNewPnrNo(enterpriseId, username, orderId, "xxx");
    }
  }

  private String getPsgMobileFromFlightOrder(final int enterpriseId, final String flightOrderNo,
                                             final String psgName, final String idNo) {
    FlightOrder flightOrder = flightOrderDao.getOrderDetailByOrderNo(enterpriseId, flightOrderNo);
    if (flightOrder == null) {
      return null;
    }
    for (FlightOrderPassenger flightOrderPassenger : flightOrder.getPassengers()) {
      if (flightOrderPassenger.getName().equalsIgnoreCase(psgName)
              && flightOrderPassenger.getIdNo().equalsIgnoreCase(idNo)) {
        return flightOrderPassenger.getMobile();
      }
    }

    return null;
  }

  @Override
  public int cancelFlightOrderPnr(final int enterpriseId, final String agentName, FlightOrder flightOrder, String remark) {
    final String pnrNo = flightOrder.getPnrNo();
    CmdResponse cmdResponse = execApiXePnr(enterpriseId, agentName, pnrNo, flightOrder.getOrderNo(), remark);

    if (cmdResponse.getCode() == 1) {
      //调用成功
      flightOrderDao.appendFlightOrderLog(enterpriseId, agentName, flightOrder.getId(), "取消编码" + pnrNo + "成功: " + cmdResponse.getMsg());
      return 1;
    } else {
     //调用失败
      flightOrderDao.appendFlightOrderLog(enterpriseId, agentName, flightOrder.getId(), "取消编码" + pnrNo + "失败: " + cmdResponse.getMsg());
      return 0;
    }
  }


  @Override
  public void refreshChangeOrderPnrDetail(final int enterpriseId, final String username, final FlightChangeOrder changeOrder) {
    String pnrNo = changeOrder.getNewPnrNo();
    if (pnrNo == null || pnrNo.trim().length() < 6) {
      //没有新编码，则使用老编码
      pnrNo = changeOrder.getOldPnrNo();
    }
    if (pnrNo == null || pnrNo.trim().length() < 6) {
      //改签单中未找到编码
      return;
    }

    RtpnrResponse response = execApiRtPnr(enterpriseId, username, pnrNo, changeOrder.getOrderNo());
    if (response.getCode() == 1 && pnrNo.equalsIgnoreCase(response.getPnrInfo().getPnr())) {
      // 调用成功
      final String pnrDetail = response.getPnrInfo().getPnrDetail();
      changeOrderDao.updateChangeOrderRefreshPnrStatus(enterpriseId, username, changeOrder.getId());
      updatePnrDetail(enterpriseId, pnrDetail);
    } else if (response.getCode() != 1) {
      // 调用失败
      changeOrderDao.updateChangeOrderRefreshPnrStatusFailed(enterpriseId, username, changeOrder.getId(), response.getCode() + ": " + response.getMsg());
    }
  }

  @Override
  public void refreshFlightOrderDetrDetail(final int enterpriseId, final String username, final FlightOrder flightOrder) {
    int detrCount = 0;
    for (FlightOrderPassenger psgInfo: flightOrder.getPassengers()) {
      List<String> ticketNos = FlightTicketUtil.processTicketNo(psgInfo.getTicketNo(), psgInfo.getTicketCount());
      for(String ticketNo: ticketNos) {
        //TODO 需要检查票号是否为终态，如果是终态，则不用再次DETR yfdai 2021-10-29
        if (execRefreshFlightOrderDetrInfo(enterpriseId, username, ticketNo, flightOrder) == 0) {
          return;
        } else {
          detrCount++;
        }
      }
    }

    if (detrCount >= flightOrder.getPassengers().size()) {
      flightOrderDao.updateFlightOrderDetrStatus(enterpriseId, username, flightOrder.getId(), 1, "Successful");
    } else {
      flightOrderDao.updateFlightOrderDetrStatus(enterpriseId, username, flightOrder.getId(), 0, "fail?");
    }
  }

  /**
   * 执行对机票订单中的票号进行DETR的任务
   * @param enterpriseId 企业id
   * @param username 用户名
   * @param ticketNo 票号
   * @param flightOrder 机票订单
   * @return 0 - detr失败， 1- detr成功
   */
  private int execRefreshFlightOrderDetrInfo(final int enterpriseId, final String username, final String ticketNo,
                                             final FlightOrder flightOrder) {
    //检查该票号今天是否已经有DETR记录
    var detrInfo1 =detrDao.getByTicketNo(enterpriseId, ticketNo.replace("-", ""));
    if (detrInfo1 != null && detrInfo1.getCreateDate().getTime() == DateUtil.getCurDate().getTime()) {
      return 1;
    }


    DetrResponse response = execApiDetr(enterpriseId, username, ticketNo, flightOrder.getOrderNo(), "更新DETR内容");

    if (response.getCode() != 1) {
      //接口调用失败（业务逻辑）
      if (response.getMsg() != null) {
        flightOrderDao.appendFlightOrderLog(enterpriseId, username, flightOrder.getId(), "DETR: " + response.getCode() + ", " + response.getMsg());
        if (response.getMsg().contains("AUTHORITY")
                || response.getMsg().contains("INVALID 3-DIGIT AIRLINE NUMBER")
                || response.getMsg().contains("ET TICKET NUMBER IS NOT EXIST")) {
          flightOrderDao.updateFlightOrderDetrStatus(enterpriseId, username, flightOrder.getId(), 4, ticketNo + ": " +response.getMsg());
        } else if (response.getMsg().contains("ET TICKET NUMBER IS NOT EXIST")) {
          DetrInfo detrInfo = new DetrInfo();
          detrInfo.setEnterpriseId(flightOrder.getEnterpriseId());
          detrInfo.setCreateDate(DateUtil.getCurDate());
          detrInfo.setTicketNo(ticketNo.replace("-", ""));

          detrInfo.setSellDate(flightOrder.getEtdzDate());
          detrInfo.setDetrDetail("ET TICKET NUMBER IS NOT EXIST");

          detrDao.create(detrInfo);

          flightOrderDao.updateFlightOrderDetrStatus(enterpriseId, username, flightOrder.getId(), 1, ticketNo + ": " + response.getMsg());
        } else {
          //防止不停的去DETR同一个票号 yfdai 2021-10-30
          flightOrderDao.updateFlightOrderDetrStatus(enterpriseId, username, flightOrder.getId(), 2, ticketNo + ": " +response.getMsg());
        }
      }
      return 0;
    }

    DetrInfo detrInfo = new DetrInfo();
    detrInfo.setEnterpriseId(flightOrder.getEnterpriseId());
    detrInfo.setCreateDate(DateUtil.getCurDate());
    detrInfo.setTicketNo(ticketNo.replace("-", ""));

    detrInfo.setSellDate(flightOrder.getEtdzDate());

    detrInfo.setDetrDetail(response.getDetrInfo().getDetrDetail());

    detrInfo.setType3(flightOrder.getIntlTicket() + "");
    detrInfo.setPsgName(response.getDetrInfo().getName());
    String segInfo = null;
    int usedCount = 0;
    int unusedCount = 0;
    for (DetrFlightInfo fltInfo : response.getDetrInfo().getFlights()) {
      String temp = fltInfo.getDport() + fltInfo.getAport() + "/" + fltInfo.getDdate() + "/" + fltInfo.getCarrier() + fltInfo.getFlightNo() + "/" + fltInfo.getTicketStatus();
      segInfo = segInfo == null ? temp : segInfo + "//" + temp;

      if (DETR_OPEN_FOR_USE.equalsIgnoreCase(fltInfo.getTicketStatus())) {
        unusedCount++;
      } else if (DETR_USED_FLOWN.equalsIgnoreCase(fltInfo.getTicketStatus())) {
        usedCount++;
      }

      DetrInfoFlight detrInfoFlight = new DetrInfoFlight();
      detrInfoFlight.setEnterpriseId(flightOrder.getEnterpriseId());
      detrInfoFlight.setSegOrder(fltInfo.getSegOrd());
      detrInfoFlight.setDport(fltInfo.getDport());
      detrInfoFlight.setAport(fltInfo.getAport());
      String ddate = DateUtil.convertEtermDate(fltInfo.getDdate(), null, flightOrder.getEtdzDate());
      detrInfoFlight.setDdate(ddate);
      detrInfoFlight.setFlightNo(fltInfo.getCarrier().trim() + fltInfo.getFlightNo().trim());
      detrInfoFlight.setSubClass(fltInfo.getSubclass());
      detrInfoFlight.setDtime(fltInfo.getDtime());
      detrInfoFlight.setTicketStatus(fltInfo.getTicketStatus());

      detrInfo.getFlights().add(detrInfoFlight);
      detrInfoFlight.setDetrInfo(detrInfo);
    }

    detrInfo.setSegInfo(segInfo);

    //设置使用状态
    processDetrUsedStatus(detrInfo, usedCount, unusedCount);

    try {
      return detrDao.create(detrInfo);
    } catch (Exception ex) {
      return doUpdateDetrInfo(detrInfo);
    }
  }

  /**
   * 根据使用和未使用的航段数，设置detr的使用状态
   * @param detrInfo detr信息
   * @param usedCount 已使用的航段数量
   * @param unusedCount 未使用的航段数量
   */
  private void processDetrUsedStatus(final DetrInfo detrInfo, final int usedCount, final int unusedCount) {
    if (unusedCount > 0 && usedCount == 0) {
      detrInfo.setIsUsed("0");
    } else if (unusedCount > 0 && usedCount > 0) {
      detrInfo.setIsUsed("1");
    } else if (unusedCount == 0 && usedCount > 0) {
      detrInfo.setIsUsed("2");
    }
  }

  @Override
  public void refreshChangeOrderDetrDetail(final int enterpriseId, final String username, FlightChangeOrder changeOrder) {
    final Date saleDate = changeOrder.getCreateTime();
    final String ticketNo = changeOrder.getNewTicketNo().length() >= 13 ?
            changeOrder.getNewTicketNo() :
            changeOrder.getBalanceCode() + "-" + changeOrder.getTicketNo();

    DetrResponse response = execApiDetr(enterpriseId, username, ticketNo, changeOrder.getChangeOrderNo(), "更新改签单DETR内容");


    //获取票号信息失败
    if (response.getCode() != 1) {
      changeOrderDao.appendFlightChangeOrderLog(enterpriseId, changeOrder.getId(), username, "DETR: " + response.getCode() + ", " + response.getMsg());
      changeOrderDao.updateChangeOrderDetrStatus(enterpriseId, username, changeOrder.getId(), 4);
      return;
    }

    int detrCount = processDetrResult(changeOrder.getEnterpriseId(), saleDate, ticketNo,
            changeOrder.getIntlTicket(), response);

    if (detrCount == 1) {
      changeOrderDao.updateChangeOrderDetrStatus(enterpriseId, username, changeOrder.getId(), 1);
    } else {
      changeOrderDao.updateChangeOrderDetrStatus(enterpriseId, username, changeOrder.getId(), 4);
    }
  }

  private int processDetrResult(final int enterpriseId, final Date saleDate, final String ticketNo,
                                final int intlTicket, DetrResponse response) {
    int detrCount = 0;

    DetrInfo detrInfo = new DetrInfo();
    detrInfo.setEnterpriseId(enterpriseId);
    detrInfo.setTicketNo(ticketNo.replace("-", ""));
    detrInfo.setSellDate(saleDate);

    detrInfo.setCreateDate(DateUtil.getCurDate());
    detrInfo.setDetrDetail(response.getDetrInfo().getDetrDetail());

    detrInfo.setType3(intlTicket + "");
    detrInfo.setPsgName(response.getDetrInfo().getName());

    String segInfo = null;
    int usedCount = 0;
    int unusedCount = 0;
    for (DetrFlightInfo fltInfo : response.getDetrInfo().getFlights()) {
      String temp = fltInfo.getDport() + fltInfo.getAport() + "/" + fltInfo.getDdate() + "/" + fltInfo.getCarrier() + fltInfo.getFlightNo() + "/" + fltInfo.getTicketStatus();
      segInfo = segInfo == null ? temp : segInfo + "//" + temp;

      if ("OPEN FOR USE".equalsIgnoreCase(fltInfo.getTicketStatus())) {
        unusedCount++;
      } else if ("USED/FLOWN".equalsIgnoreCase(fltInfo.getTicketStatus())) {
        usedCount++;
      }

      DetrInfoFlight detrInfoFlight = new DetrInfoFlight();
      detrInfoFlight.setEnterpriseId(enterpriseId);
      detrInfoFlight.setSegOrder(fltInfo.getSegOrd());
      detrInfoFlight.setDport(fltInfo.getDport());
      detrInfoFlight.setAport(fltInfo.getAport());
      String ddate = DateUtil.convertEtermDate(fltInfo.getDdate(), null, saleDate);
      detrInfoFlight.setDdate(ddate);
      detrInfoFlight.setFlightNo(fltInfo.getCarrier().trim() + fltInfo.getFlightNo().trim());
      detrInfoFlight.setSubClass(fltInfo.getSubclass());
      detrInfoFlight.setDtime(fltInfo.getDtime());
      detrInfoFlight.setTicketStatus(fltInfo.getTicketStatus());

      detrInfo.getFlights().add(detrInfoFlight);
      detrInfoFlight.setDetrInfo(detrInfo);
    }
    detrInfo.setSegInfo(segInfo);

    processDetrUsedStatus(detrInfo, usedCount, unusedCount);

    try {
      int retCode = detrDao.create(detrInfo);
      if (retCode > 0) {
        detrCount++;
      }
    } catch (Exception ex) {
      logger.warn(ex.getMessage());

      if (doUpdateDetrInfo(detrInfo) > 0) {
        detrCount++;
      }
    }

    return detrCount;
  }

  @Override
  public void refreshRefundOrderDetrDetail(int enterpriseId, String username, FlightRefundOrder orderInfo) {
    final Date saleDate = orderInfo.getCreateTime();
    final String ticketNo = orderInfo.getBalanceCode() + "-" + orderInfo.getTicketNo();

    logger.info("refreshRefundOrderDetrDetail: {}.", orderInfo.getRefundOrderNo());

    var response = execApiDetr(enterpriseId, username, ticketNo, orderInfo.getRefundOrderNo(), "更新退票单DETR内容");

    //获取票号信息失败
    if (response.getCode() != 1) {
      refundOrderDao.appendRefundOrderLog(enterpriseId, username, orderInfo.getId(),  "DETR: " + response.getCode() + ", " + response.getMsg());
      refundOrderDao.updateRefundOrderDetrStatus(enterpriseId, username, orderInfo.getId(), 4);
      return;
    }

    int detrCount = processDetrResult(orderInfo.getEnterpriseId(), saleDate, ticketNo, orderInfo.getIntlTicket(), response);


    if (detrCount == 1) {
      refundOrderDao.updateRefundOrderDetrStatus(enterpriseId, username, orderInfo.getId(), 1);
    } else {
      refundOrderDao.updateRefundOrderDetrStatus(enterpriseId, username, orderInfo.getId(), 4);
    }
  }

  @Override
  public List<TicketSale> tpr(int enterpriseId, String username, final int deviceId, Date tprDate) {
    TslResponse response = execApiTpr(enterpriseId, username, tprDate, deviceId,
            "获取TPR(" + deviceId + ", " + DateUtil.formatDate(tprDate, DATE_YYYY_MM_DD) + ")");
    if (response.getCode() != 1) {
      logger.error("tpr result: {}, {}", response.getCode(), response.getMsg());
      return new ArrayList<>();
    }

    List<TicketSale> list = new ArrayList<>();
    for(TslItemContent item: response.getContent().getItems()) {
      TicketSale ts = new TicketSale();
      ts.setEnterpriseId(enterpriseId);
      ts.setSellDate(tprDate);
      ts.setDeviceId(deviceId);

      ts.setPrice(item.getPrice());
      ts.setTax(item.getTax());
      ts.setCommission(item.getCommission());

      ts.setTicketNo(item.getTicketNo());
      ts.setOrig(item.getDport());
      ts.setDest(item.getAport());
      ts.setPnrNo(item.getPnrNo());
      if ("TICKET".equalsIgnoreCase(item.getStatus())) {
        ts.setTicketStatus(0);
      } else if ("ET-REFUND".equalsIgnoreCase(item.getStatus())) {
        ts.setTicketStatus(4);
      } else if ("EX".equalsIgnoreCase(item.getStatus())) {
        ts.setTicketStatus(1);
      } else {
        ts.setTicketStatus(-1);
      }

      list.add(ts);
    }

    return list;
  }

  @Override
  public EtdzResponse etdz(int enterpriseId, String username, FlightOrder orderInfo) {
    EtdzRequest request = new EtdzRequest();

    //如果设置了开票价格，就使用该值；否则默认使用订单中的成人票面价
    final int etdzFare = orderInfo.getAutoTicketingPrice() > 0 ? orderInfo.getAutoTicketingPrice()
            : (int) orderInfo.getPrice();
    final int price = etdzFare + (int)orderInfo.getTax();

    request.setPnrNo(orderInfo.getPnrNo());
    request.setPrice(price + "");

    //使用订单中的大客户代码
    if (orderInfo.getKeyCustomerNo() != null && orderInfo.getKeyCustomerNo().trim().length() > 0) {
      request.setKeyCustomerCode(orderInfo.getKeyCustomerNo().trim());
    }

    final int queryId = userDao.createEtermCmdLog(enterpriseId, username, "自动ETDZ", orderInfo.getOrderNo());

    SzkjEtermService szkjEtermService = createSzkjEtermService(enterpriseId);

    EtdzResponse response = szkjEtermService.etdz(getEtermUsername(enterpriseId), getEtermPassword(enterpriseId), queryId, request);

    userDao.updateEtermCmdLog(queryId, response.getRequestStr(), response.getResponseStr());

    return response;
  }

  @Override
  public RtpnrResponse rt(int enterpriseId, String username, String pnrNo) {
    return execApiRt(enterpriseId, username, pnrNo, null, pnrNo, "提取编码内容");
  }

  @Override
  public void qt(final int enterpriseId, final String username) {
    QtResponse qtRes = execApiQt(enterpriseId, username);
    if (qtRes.getCode() == 1) {
      //QT接口调用成功
      for(QtItem qtItem: qtRes.getItems()) {
        if (qtItem.getQuantity() < 1) {
          continue;
        }

        execQn(enterpriseId, username, qtItem.getQtype());
      }
    }
  }

  @Override
  public void checkFd(int enterpriseId, String username) {
    synchronized (this) {
      int loopCount = 0;
      while (true) {
        loopCount++;
        int count = execCheckFd(enterpriseId, username);
        if (count == -1 || loopCount >= 15) {
          break;
        }
      }
    }

  }

  /**
   * 执行FD下载任务
   */
  private int execCheckFd(final int enterpriseId, final String username) {
    final String fdRequest = redisDao.getFromList(FlightPriceCache.FD_QUEUE);
    if (fdRequest == null) {
      return -1;
    }

    final String[] items = fdRequest.split(",");
    if (items.length < 3) {
      return -1;
    }
    final String dport = items[0];
    final String aport = items[1];
    final String carrier = items[2];
    List<FlightPriceCache> priceCaches = flightPolicyDao.searchFlightPriceCache(dport, aport, carrier);
    if (!priceCaches.isEmpty()) {
      return 1;
    }

    FdResponse response = execApiFd(enterpriseId, username, dport, aport, carrier);
    if (response.getCode() != 1) {
      //接口调用不成功
      return -2;
    }

    List<FlightPriceCache> flightPriceCaches = new ArrayList<>();
    for (FdPriceItem item : response.getContent().getPrices()) {
      processFdResult(flightPriceCaches, item);
    }

    if (flightPriceCaches.isEmpty()) {
      return -3;
    } else {
      return flightPolicyDao.createFlightPriceCaches(flightPriceCaches);
    }
  }

  /**
   * 处理FD结果项，并合并返程到已有的项目中
   */
  private void processFdResult(final List<FlightPriceCache> flightPriceCaches, final FdPriceItem item) {
    if (StringUtils.isEmpty(item.getSinglePrice())
            && !StringUtils.isEmpty(item.getRoundPrice())) {
      //当前项目只包含往返价格
      for (FlightPriceCache cache : flightPriceCaches) {
        if (item.getDport().equalsIgnoreCase(cache.getDport()) &&
                item.getAport().equalsIgnoreCase(cache.getAport()) &&
                item.getCarrier().equalsIgnoreCase(cache.getCarrier()) &&
                item.getFaeBasis().equalsIgnoreCase(cache.getFareClass()) &&
                cache.getRtPrice() == 0) {
          cache.setRtPrice((int) Double.parseDouble(item.getRoundPrice()));
          break;
        }
      }
      return;
    }
    FlightPriceCache p = new FlightPriceCache();
    p.setDport(item.getDport());
    p.setAport(item.getAport());
    p.setCarrier(item.getCarrier());

    p.setSubclass(item.getSubClass());
    p.setCabinClass(item.getCabinCode());
    p.setFareClass(item.getFaeBasis());

    if (!StringUtils.isEmpty(item.getSinglePrice())) {
      p.setPrice((int) Double.parseDouble(item.getSinglePrice()));
    }
    if (!StringUtils.isEmpty(item.getRoundPrice())) {
      p.setRtPrice((int) Double.parseDouble(item.getRoundPrice()));
    }

    try {
      p.setFdDate(DateUtil.convertToDate(DateUtil.convertEtermDate(item.getStartTime()), DATE_YYYY_MM_DD));
      p.setEffectDate(DateUtil.convertToDate(DateUtil.convertEtermDate(item.getEffectDate()), DATE_YYYY_MM_DD));
      if (!StringUtils.isEmpty(item.getExpireDate())) {
        p.setExpireDate(DateUtil.convertToDate(DateUtil.convertEtermDate(item.getExpireDate()), DATE_YYYY_MM_DD));
      }
    } catch (ParseException e) {
      e.printStackTrace();
    }

    flightPriceCaches.add(p);
  }

  private void execQn(final int enterpriseId, final String username, final String qtype) {
    int qnCount = 0;
    while (true) {
      qnCount++;
      if (qnCount > 10) {
        break;
      }
      QnResponse response = execApiQn(enterpriseId, username, qtype);

      if (response.getCode() == 1 || response.getCode() == 150001) {
        //150001 	结果中未分析出PNR
        Qinfo qinfo = new Qinfo();
        qinfo.setEnterpriseId(enterpriseId);
        qinfo.setQtype(qtype);
        qinfo.setPnrno(response.getPnrNo());
        qinfo.setQdetail(response.getPnrDetail());
        qinfo.setUsername(username);

        pnrDao.createQinfo(qinfo);

        if (!StringUtils.isEmpty(response.getPnrNo())) {
          execProcessQinfo(enterpriseId, username, response.getPnrNo().trim(), qtype, response.getPnrDetail());
        }

        if (response.getQuantity() == 0) {
          return;
        }
      } else {
        return;
      }
    }
  }

  /**
   * 处理Q信息的处理业务规则
   */
  private void execProcessQinfo(final int enterpriseId, final String username, final String pnrNo,
                              final String qtype, final String qdetail) {
    if (!"SC".equalsIgnoreCase(qtype)) {
      return;
    }

    //执行通知，告知有航变
    final String title = "航变信息(" + pnrNo + ")通知";
    final String toParty = EntDepartment.DEPT_CUSTOMER_SERVICE + "|" + EntDepartment.DEPT_ADMINISTRATOR;
    doSendFlightOrderAlertByTaskCardMsg(enterpriseId, 0, title, qdetail, toParty);

    processScOfFlightOrder(enterpriseId, username, qtype, pnrNo);
    processScOfChangeOrder(enterpriseId, username, qtype, pnrNo);
  }

  //处理机票订单的SC通知
  private void processScOfFlightOrder(final int enterpriseId, final String username,
                                      final String qtype, final String pnrNo) {
    List<FlightOrder> flightOrders = flightOrderDao.searchFlightOrdersByPnrNo(enterpriseId, pnrNo);
    if (flightOrders.isEmpty()) {
      doSendAlert(enterpriseId, qtype + "信息：通过编码" + pnrNo + "未找到机票订单", null, EntDepartment.DEPT_ADMINISTRATOR);
      return;
    }

    for (FlightOrder flightOrder : flightOrders) {
      flightOrderDao.updateFlightOrderNotice(enterpriseId, username, flightOrder.getId(), 1, qtype + "信息");
      doRefreshFlightOrderPnrDetail(enterpriseId, username, flightOrder.getId(), flightOrder.getOrderNo(), pnrNo);

      //TODO 发送企业微信通知给订单的创建人, 如果是客户自助下单呢？如果是员工，可以生成链接，让其直接进入系统查看该订单
      final String op1 = flightOrder.getOperator();
      final User user = userDao.getUserByUsername(op1);
      final String content =  "机票订单(订单号: "
              + flightOrder.getOrderNo() + ", 编码: "
              + pnrNo + ", " + op1 + ") 有" + qtype + "信息，请及时处理。";
      if (user.getEnterpriseId() == enterpriseId && !StringUtils.isEmpty(user.getWwUserId())) {
        //员工创建的订单
        doSendAlert(enterpriseId, content, user.getWwUserId(), 0);
      } else {
        doSendAlert(enterpriseId, content, null, EntDepartment.DEPT_ADMINISTRATOR);
      }

      //发送给群聊会话
      try {
        sendEtermQueueToWwAppChat(enterpriseId, qtype, content);
      } catch (Exception ex) {
        logger.error(ex.getMessage());
      }
    }
  }

  //处理改签单的SC通知
  private void processScOfChangeOrder(final int enterpriseId, final String username,
                                      final String qtype, final String pnrNo) {
    List<FlightChangeOrder> changeOrders = changeOrderDao.searchChangeOrderByPnrNo(enterpriseId, pnrNo);
    if (changeOrders.isEmpty()) {
      return;
    }

    for (var changeOrder : changeOrders) {
      refreshChangeOrderPnrDetail(enterpriseId, username, changeOrder);

      final String op1 = changeOrder.getOperator();
      final User user = userDao.getUserByUsername(op1);
      final String content =  String.format("改签单(订单号: %s, 编码: %s, %s) 有%s信息，请及时处理。", changeOrder.getChangeOrderNo(), pnrNo, op1, qtype);
      if (user.getEnterpriseId() == enterpriseId && !StringUtils.isEmpty(user.getWwUserId())) {
        //员工创建的订单
        doSendAlert(enterpriseId, content, user.getWwUserId(), 0);
      }

      //发送给群聊会话
      try {
        sendEtermQueueToWwAppChat(enterpriseId, qtype, content);
      } catch (Exception ex) {
        logger.error(ex.getMessage());
      }
    }
  }

  private int doUpdateDetrInfo(DetrInfo newDetrInfo) {
    DetrInfo oldDetrInfo = detrDao.getByTicketNo(newDetrInfo.getEnterpriseId(), newDetrInfo.getTicketNo());
    if (oldDetrInfo == null) {
      return 0;
    }

    oldDetrInfo.setIsUsed(newDetrInfo.getIsUsed());
    for(DetrInfoFlight oldFlight: oldDetrInfo.getFlights()) {
      for(DetrInfoFlight newFlight: newDetrInfo.getFlights()) {
        if (newFlight.getDport().equalsIgnoreCase(oldFlight.getDport())
          && newFlight.getAport().equalsIgnoreCase(oldFlight.getAport())
                && newFlight.getFlightNo().equalsIgnoreCase(oldFlight.getFlightNo())
        ) {
          oldFlight.setTicketStatus(newFlight.getTicketStatus());
        }
      }
    }

    return detrDao.update(oldDetrInfo);
  }

  private CmdResponse execApiXePnr(final int enterpriseId, final String username, final String pnrNo,
                                   final String orderNo, final String remark) {
    PnrXeRequest request = new PnrXeRequest();
    request.setPnrNo(pnrNo);

    final int queryId = userDao.createEtermCmdLog(enterpriseId, username, remark, orderNo);

    SzkjEtermService szkjEtermService = createSzkjEtermService(enterpriseId);

    CmdResponse response = szkjEtermService.xepnr(getEtermUsername(enterpriseId), getEtermPassword(enterpriseId), queryId, request);

    userDao.updateEtermCmdLog(queryId, response.getRequestStr(), response.getResponseStr());

    return response;
  }

  private DetrResponse execApiDetr(final int enterpriseId, final String username, final String ticketNo,
                                   final String orderNo, final String remark) {
    DetrRequest request = new DetrRequest();
    request.setTicketNo(ticketNo);
    request.setGetRawdata(1);

    final int queryId = userDao.createEtermCmdLog(enterpriseId, username, remark, orderNo);

    SzkjEtermService szkjEtermService = createSzkjEtermService(enterpriseId);

    DetrResponse response = szkjEtermService.detr(getEtermUsername(enterpriseId), getEtermPassword(enterpriseId), queryId, request);

    userDao.updateEtermCmdLog(queryId, response.getRequestStr(), response.getResponseStr());

    return response;
  }

  private TslResponse execApiTpr(final int enterpriseId, final String username, final Date tprDate, final int deviceId, final String remark) {
    TslRequest request = new TslRequest();

    request.setCmd("TPR");
    request.setPrintid(deviceId);
    request.setTicketDate(DateUtil.formatDate(tprDate, "yyyy-MM-dd"));

    final int queryId = userDao.createEtermCmdLog(enterpriseId, username, remark, null);

    SzkjEtermService szkjEtermService = createSzkjEtermService(enterpriseId);
    TslResponse response = szkjEtermService.tsl(getEtermUsername(enterpriseId), getEtermPassword(enterpriseId), queryId, request);

    userDao.updateEtermCmdLog(queryId, response.getRequestStr(), response.getResponseStr());

    return response;
  }

  private QtResponse execApiQt(final int enterpriseId, final String username) {
    QtRequest request = new QtRequest();
    final int queryId = userDao.createEtermCmdLog(enterpriseId, username, "QT", "");

    SzkjEtermService szkjEtermService = createSzkjEtermService(enterpriseId);
    QtResponse response = szkjEtermService.qt(getEtermUsername(enterpriseId), getEtermPassword(enterpriseId), queryId, request);

    userDao.updateEtermCmdLog(queryId, response.getRequestStr(), response.getResponseStr());

    return response;
  }

  private QnResponse execApiQn(final int enterpriseId, final String username, final String qtype) {
    final int queryId = userDao.createEtermCmdLog(enterpriseId, username, qtype, "");

    QnRequest request = new QnRequest();
    request.setQtype(qtype);

    SzkjEtermService szkjEtermService = createSzkjEtermService(enterpriseId);
    QnResponse response = szkjEtermService.qn(getEtermUsername(enterpriseId), getEtermPassword(enterpriseId), queryId, request);

    userDao.updateEtermCmdLog(queryId, response.getRequestStr(), response.getResponseStr());

    return response;
  }

  private FdResponse execApiFd(final int enterpriseId, final String username, final String dport, final String aport, final String carrier) {
    final int queryId = userDao.createEtermCmdLog(enterpriseId, username, "FD", "");

    FdRequest request = new FdRequest();
    request.setDport(dport);
    request.setAport(aport);
    request.setCarrier(carrier);

    SzkjEtermService szkjEtermService = createSzkjEtermService(enterpriseId);
    FdResponse response = szkjEtermService.fd(getEtermUsername(enterpriseId), getEtermPassword(enterpriseId), queryId, request);

    userDao.updateEtermCmdLog(queryId, response.getRequestStr(), response.getResponseStr());

    return response;
  }


}
